package com.wrupple.vegetate.server;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.wrupple.vegetate.domain.VegetateToken;
import com.wrupple.vegetate.domain.exceptions.IntegrationLayerException;
import com.wrupple.vegetate.server.service.VegetateRequestTokenizer;

public abstract class AbstractVegetateServlet extends HttpServlet {

	private static final long serialVersionUID = -2975782127127862345L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String path = req.getRequestURI();
		if (path == null) {
			handleError(new NullPointerException("unable to read path"),req,resp);
		} else {
			VegetateRequestTokenizer tokenizer = getRequestTokenizer();
			VegetateToken[] tokens = tokenizer.getRequestTokens(req);
			if (tokens.length == 0) {
				handleError(new IllegalArgumentException("zero argument path"),req,resp);
			} else {
				VegetateServiceLocator current = getRootModule();
				VegetateServiceLocator child;
				String key ;
				Map<String,String> map = new HashMap<String, String>();
				try {
					VegetateToken token;
					for (int  i = 0 ;  i < tokens.length;i++) {
						token = tokens[i];
						if(token==null){
							break;
						}else{
							key = current.getName();
							map.put(key, token.getName());
							System.err.println("Token: "+token);
							System.err.println("Mapped: "+map);
							if(i==0){
								//skip root reference ¿fixme?
							}else{
								child = current.getServiceBranchForToken(token);
								if(child!=null){
									current=child;
								}
							}
							System.err.println("Service: "+current.getClass().getCanonicalName());
						}
					}
					map = Collections.unmodifiableMap(map);
					
					current.serve(req, resp, map);
				} catch (IntegrationLayerException e) {
					handleError(e,req,resp);
				}
			}
		}
		resp.setStatus(HttpServletResponse.SC_OK);
	}

	private void handleError(Exception e,
			HttpServletRequest req, HttpServletResponse resp) throws IOException {
		resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doPost(req, resp);
	}

	protected abstract VegetateRequestTokenizer getRequestTokenizer();

	protected abstract VegetateServiceLocator getRootModule();
}
